package org.libarae.communication.response;

import java.io.ByteArrayOutputStream;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.libarae.communication.HTTPUtils;
import org.libarae.communication.XmlParseException;
import org.libarae.communication.common.Book;
import org.libarae.communication.common.Type;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;


public class BookInfoResponse extends Response{	
	private Book mBook = new Book();
	private boolean isMyBook = false;

	public BookInfoResponse(int status){
		super(Type.BOOK_INFO, status);		
	}
	
	public BookInfoResponse(int status, Book book, boolean isMyBook){
		super(Type.BOOK_INFO, status);		
		setBook(book);
		setMyBook(isMyBook);
	}
	
	
	@Override
	public String createXML() throws XmlParseException {
		Document doc;
		try{
			//setup the factory to build the xml
			DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
			DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
			doc = documentBuilder.newDocument();
		}
		catch (Exception e) {
			throw new XmlParseException("Error creating XML Builder",e);
		}
		
		//create the xml
		Element rootElement = doc.createElement("type");
		rootElement.setAttribute("typeID", super.getType()+"");
		doc.appendChild(rootElement);
		//user name
		Element node = doc.createElement("mStatus");
		node.setTextContent(getStatus()+"");
		rootElement.appendChild(node);

		node = doc.createElement("mBook");
		mBook.createXml(doc, node);
		rootElement.appendChild(node);
		
		node = doc.createElement("isMyBook");
		if(isMyBook)
			node.setTextContent("1");
		else
			node.setTextContent("0");
		rootElement.appendChild(node);
		
		
		
		//export the xml to a string
		String output = null;
		try {
			ByteArrayOutputStream byteArrayOutput = new ByteArrayOutputStream();
			TransformerFactory transformerFactory = TransformerFactory.newInstance();
			Transformer transformer = transformerFactory.newTransformer();
			DOMSource source = new DOMSource(doc);
			StreamResult result = new StreamResult(byteArrayOutput);
			transformer.transform(source, result);
			output = byteArrayOutput.toString();
		}
		catch (Exception e) {
			throw new XmlParseException("Error outputting XML to string", e);
		}
		
		//return the string
		return output;
	}

	@Override
	public void decodeXML(Document document) {
		// get the document root and node list
		Element root = document.getDocumentElement();
		NodeList nodeList = root.getChildNodes();

		// set all of the nodes in their proper places
		for (int i = 0; i < nodeList.getLength(); i++) {
			// find what node we have
			String nodeName = nodeList.item(i).getNodeName();
			if (nodeName.equals("mStatus")) {
				setStatus(Integer.parseInt(nodeList.item(i).getTextContent()));
			}
			else if (nodeName.equals("mBook")) {
				mBook = new Book();
				mBook.decodeXML(nodeList.item(i));
			}
			else if (nodeName.equals("isMyBook")) {
				if(Integer.parseInt(nodeList.item(i).getTextContent()) == 1)
					isMyBook = true;
				else 
					isMyBook = false;
			}			
			else {
				System.err.println("Unknow field in object XML: " + nodeName);
			}
		}	
	}
	
	/**
	 * @return the mBook
	 */
	public Book getBook() {
		return mBook;
	}

	/**
	 * @param mBook the mBook to set
	 */
	public void setBook(Book mBook) {
		if(mBook == null)
			this.mBook = new Book();
		else
			this.mBook = mBook;
	}

	/**
	 * @return the isMyBook
	 */
	public boolean isMyBook() {
		return isMyBook;
	}

	/**
	 * @param isMyBook the isMyBook to set
	 */
	public void setMyBook(boolean isMyBook) {
		this.isMyBook = isMyBook;
	}

	@Override
	public String createHTML() {
		Book b = getBook();

		StringBuilder sb = new StringBuilder();
		
		sb.append("<div class=\"holder\"><center>");	
		
		if(b.getPicture() != null)
		{
			sb.append("<img src=\"image?mBid=" + b.getBID()  +"\" width=\"130px\" alt=\"some_text\"/>");		
		}
		sb.append("</center><div style=\"padding:5px;\">");
		sb.append("<table border=\"0\">");

		//Create a new row for each book result
			sb.append("<tr>");
			sb.append("<td><strong>").append("Title:").append("</strong></td>").append(p(b.getTitle()));
			sb.append("</tr>");
			
			sb.append("<tr>");
			sb.append("<td><strong>").append("Author:").append("</strong></td>").append(p(b.getAuthor()));
			sb.append("</tr>");
			
			sb.append("<tr>");
			sb.append("<td><strong>").append("ISBN:").append("</strong></td>").append(p(b.getISBN()));
			sb.append("</tr>");
			
			sb.append("<tr>");
			sb.append("<td><strong>").append("Publisher:").append("</strong></td>").append(p(b.getPublisher()));
			sb.append("</tr>");
			
			
			sb.append("<tr>");
			sb.append("<td><strong>").append("Pub. Date:").append("</strong></td>").append(p(b.getPubDate()));
			sb.append("</tr>");
			
			sb.append("<tr>");
			//TODO one there is a way to send a checkout request, make a checkout link if it is avilible
			sb.append("<td><strong>").append("Availibility:").append("</strong></td>").append(p(b.getBookStatus().toString()));
			sb.append("</tr>");
		
		sb.append("</table>");
		
		sb.append("<div style=\"padding:3px;\">");
		
		sb.append("<br/><strong>Summary:</strong>");
		if(b.getSummary() == null || b.getSummary().equals(""))
			sb.append(" No summary available");
		else
			sb.append("<p>").append(b.getSummary()).append("</p>");

		sb.append("</div></div></div></body>");
		return HTTPUtils.HTMLPageHeader("") + sb.toString();
	}
	
	/**
	 * Simple helper method to quickly pring a string or a blank if it is null & have <td> tags around it
	 */
	private String p(String s)
	{
		if (s == null)
			return "<td></td>";
		else return "<td>" + s + "</td>";
	}

}
